﻿using System.IO.Ports;
using Tester.DL645;
using Tester.DL645.Core;
using Tester.DL645.Instructions;
using Tester.DL645.Responses;

namespace Tester
{
    public partial class FrmLocalElectricityMeter : Form
    {
        public FrmLocalElectricityMeter()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmMain_Load(object sender, EventArgs e)
        {
            string[] portNames = SerialPort.GetPortNames();

            this.cbSerPort.Items.Clear();
            this.cbSerPort.Items.AddRange(portNames);


            this.btnClose.Enabled = false;
            this.btnReadAddress.Enabled = false;
            this.btnSwitchOff.Enabled = false;
            this.btnSwitchOn.Enabled = false;
            this.btnReadEnergy.Enabled = false;
            this.btnReadACurrent.Enabled = false;
            this.btnReadAVoltage.Enabled = false;


        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        public void Log(string message)
        {
            this.textBox1.AppendText(message + System.Environment.NewLine);
        }


        SerialPort mSerialPort;
        /// <summary>
        /// 打开串口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOpen_Click(object sender, EventArgs e)
        {
            try
            {
                string[] portNames = SerialPort.GetPortNames();
                var portName = this.cbSerPort.Text;
                if (!portNames.Contains(portName))
                {
                    this.Log("端口不存在:" + portName);
                    return;
                }

                int.TryParse(this.cbBaudRate.Text, out var baudRate);
                if (baudRate == 0)
                {
                    this.Log("波特率错误:" + baudRate);
                    return;
                }

                mSerialPort = new SerialPort(portName, baudRate);
                mSerialPort.DataBits = 8;
                mSerialPort.StopBits = StopBits.One;
                mSerialPort.Parity = Parity.Even;

                mSerialPort.ReadTimeout = 1000;

                mSerialPort.ReadBufferSize = 4096;

                mSerialPort.Open();

                mSerialPort.DataReceived += MSerialPort_DataReceived;
                this.btnOpen.Enabled = false;

                this.btnClose.Enabled = true;
                this.btnReadAddress.Enabled = true;
                this.btnSwitchOff.Enabled = true;
                this.btnSwitchOn.Enabled = true;
                this.btnReadEnergy.Enabled = true;  
                this.btnReadACurrent.Enabled = true;
                this.btnReadAVoltage.Enabled = true;
                //mSerialPort.WriteLine("Hello World!");
            }
            catch (Exception ex)
            {
                this.btnOpen.Enabled = true;

                this.btnClose.Enabled = false;
                this.btnReadAddress.Enabled = false;
                this.btnSwitchOff.Enabled = false;
                this.btnSwitchOn.Enabled = false;
                this.btnReadEnergy.Enabled = false;
                this.btnReadACurrent.Enabled = false;
                this.btnReadAVoltage.Enabled = false;
                this.Log(ex.Message);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        BufferManager BufferManager = new BufferManager();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            Thread.Sleep(1000);
             
        }


        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="serialPort"></param>

        public void OnDataReceived(SerialPort serialPort,ResponseType responseType)
        {
        

            byte[] buffer = new byte[1024];

            var offset = 0;

            while (serialPort.BytesToRead > 0)
            {
                int bytesRead = serialPort.Read(buffer, offset, serialPort.BytesToRead);

                offset += bytesRead;

            }

            var data = buffer.Take(offset).ToArray();
            var response = DeviceFactory.Create("0000000").CreateResponse(data, responseType);

            OnReponseReceived(response);
        }
         

        private void OnReponseReceived(AbstractReponse reponse)
        {
            this.Text = string.Empty;
            if (reponse is ErrorReponse noReponse)
            {
                this.Text = noReponse.Description;

                return;
            }

            this.txtSwitchOn.Clear();
            this.txtSwitchOff.Clear();

            if (reponse is AddressReponse addressReponse)
            {
                this.txtAddress.Text = addressReponse.Address;
            }

            else if (reponse is OnReponse onReponse)
            {

                this.txtSwitchOn.Text = onReponse.Description;


            }
            else if (reponse is OffReponse offReponse)
            {

                this.txtSwitchOff.Text = offReponse.Description;

            }
            else if (reponse is EnergyResponse energyResponse)
            {

                this.txtEnergy.Text = energyResponse.Value.ToString();

            }
            else if (reponse is PhaseCurrentResponse currentResponse)
            {

                this.txtCurrent.Text = currentResponse.Description;

            }
            else if (reponse is PhaseVoltageResponse voltageResponse)
            {

                this.txtPhaseVoltage.Text = voltageResponse.Description;


            }
            else
            {

            }

        }



        /// <summary>
        /// 关闭串口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnClose_Click(object sender, EventArgs e)
        {
            if (this.mSerialPort != null)
            {

                try
                {
                    this.mSerialPort.Close();
                }
                catch (Exception ex)
                {

                    this.Log(ex.Message);
                }
            }
        }

         
        

        /// <summary>
        /// 对表地址
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnReadAddress_Click(object sender, EventArgs e)
        {

           var instruction= new InstructionBuilder("", "0000", "02").CreateAddressInstruction();
            //var instruction = DeviceFactory.Create("", "0000", "02").CreateInstruction(InstructionType.Address);

            this.SendInstruction(instruction);

            Thread.Sleep(1000);

            this.OnDataReceived(mSerialPort, ResponseType.Address);

        }

        /// <summary>
        /// 发送指令
        /// </summary>
        /// <param name="instruction"></param>
        public void SendInstruction(AbstractInstruction instruction)
        {

            if (instruction is NoInstruction)
            {
                return;
            }

            byte[] buffers = instruction.Bytes;

            if (mSerialPort != null && mSerialPort.IsOpen)
            {
                mSerialPort.Write(buffers, 0, buffers.Length);
            }
        }

        /// <summary>
        /// 拉闸
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSwitchOff_Click(object sender, EventArgs e)
        {

            var instruction = DeviceFactory.Create(this.txtAddress.Text, "0000", "02").CreateInstruction(InstructionType.Off);

            this.SendInstruction(instruction);
            Thread.Sleep(1000);

            this.OnDataReceived(mSerialPort, ResponseType.Off);

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSwitchOn_Click(object sender, EventArgs e)
        {
            var instruction = DeviceFactory.Create(this.txtAddress.Text, "0000", "02").CreateInstruction(InstructionType.On);

            this.SendInstruction(instruction);
            Thread.Sleep(1000);

            this.OnDataReceived(mSerialPort, ResponseType.On);


        }

        private void btnReadEnergy_Click(object sender, EventArgs e)
        {
            var instruction = DeviceFactory.Create(this.txtAddress.Text, "0000", "02").CreateInstruction(InstructionType.Energy);

            this.SendInstruction(instruction);
            Thread.Sleep(1000);

            this.OnDataReceived(mSerialPort, ResponseType.Energy);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnReadAVoltage_Click(object sender, EventArgs e)
        {
            var instruction = DeviceFactory.Create(this.txtAddress.Text, "0000", "02").CreateInstruction(InstructionType.APhaseVoltage);

            this.SendInstruction(instruction);
            Thread.Sleep(1000);

            this.OnDataReceived(mSerialPort, ResponseType.APhaseVoltage);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>

        private void btnReadBVoltage_Click(object sender, EventArgs e)
        {
            var instruction = DeviceFactory.Create(this.txtAddress.Text, "0000", "02").CreateInstruction(InstructionType.BPhaseVoltage);

            this.SendInstruction(instruction);
            Thread.Sleep(1000);

            this.OnDataReceived(mSerialPort, ResponseType.BPhaseVoltage);

        }

        private void btnReadCVoltage_Click(object sender, EventArgs e)
        {
            var instruction = DeviceFactory.Create(this.txtAddress.Text, "0000", "02").CreateInstruction(InstructionType.CPhaseVoltage);

            this.SendInstruction(instruction);
            Thread.Sleep(1000);

            this.OnDataReceived(mSerialPort, ResponseType.CPhaseVoltage);
        }

        private void btnReadACurrent_Click(object sender, EventArgs e)
        {
            var instruction = DeviceFactory.Create(this.txtAddress.Text, "0000", "02").CreateInstruction(InstructionType.APhaseCurrent);

            this.SendInstruction(instruction);
            Thread.Sleep(1000);

            this.OnDataReceived(mSerialPort, ResponseType.APhaseCurrent);
        }

        private void btnReadBCurrent_Click(object sender, EventArgs e)
        {
            var instruction = DeviceFactory.Create(this.txtAddress.Text, "0000", "02").CreateInstruction(InstructionType.BPhaseCurrent);

            this.SendInstruction(instruction);
            Thread.Sleep(1000);

            this.OnDataReceived(mSerialPort, ResponseType.BPhaseVoltage);
        }

        private void btnReadCCurrent_Click(object sender, EventArgs e)
        {
            var instruction = DeviceFactory.Create(this.txtAddress.Text, "0000", "02").CreateInstruction(InstructionType.CPhaseCurrent);

            this.SendInstruction(instruction);
            Thread.Sleep(1000);

            this.OnDataReceived(mSerialPort, ResponseType.CPhaseCurrent   );
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnReadRatedVoltage_Click(object sender, EventArgs e)
        {

        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnReadRatedCurrent_Click(object sender, EventArgs e)
        {
            var instruction = DeviceFactory.Create(this.txtAddress.Text, "0000", "02").CreateInstruction(InstructionType.RatedCurrent);

            this.SendInstruction(instruction);
        }
    }
}
